/**
 * 
 */
package br.com.ctm.advogadope.negocio.impl;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;

import org.apache.log4j.Logger;

import br.com.ctm.advogadope.model.Tribunal;
import br.com.ctm.advogadope.model.Tribunal.TipoJuizo;
import br.com.ctm.advogadope.negocio.api.ServicoPJe;
import br.com.ctm.advogadope.negocio.api.TribunalNegocio;
import br.com.framework.negocio.exception.NegocioException;
import br.jus.cnj.intercomunicacao.servico.Intercomunicacao;
import br.jus.cnj.intercomunicacao.servico.IntercomunicacaoService;

/**
 * @author Angelina Figueiredo
 *
 */
@Singleton
@Startup
public class ServicoPJeImpl implements ServicoPJe {
	
	private static final Logger LOGGER = Logger.getLogger(ServicoPJeImpl.class);
	
	private Map<String, Intercomunicacao> servicosMap;
	
	private static final QName SERVICE_QNAME = new QName("http://www.cnj.jus.br/servico-intercomunicacao-2.1/", "IntercomunicacaoService");
	
	@Inject
	private TribunalNegocio tribunalNegocio;

	/**
	 * 
	 */
	public ServicoPJeImpl() {
		this.servicosMap = new HashMap<String, Intercomunicacao>();
	}
	
	/**
	 * @param idTribunal
	 * @param tipoJuizo
	 * @return
	 */
	private String buildIdentificador(Long idTribunal, TipoJuizo tipoJuizo) {
		return idTribunal.toString() + "|" + tipoJuizo;
	}
	
	@Override
	public Intercomunicacao getServico(Long idTribunal, TipoJuizo tipoJuizo)
			throws NegocioException {
		String identificador = buildIdentificador(idTribunal, tipoJuizo);
		Intercomunicacao servico = servicosMap.get(identificador);
		if (servico == null) {
			LOGGER.debug("Inicializando novo endpoint para o tribunalId = " + identificador);
			Tribunal tribunal = tribunalNegocio.findByID(idTribunal);
			if (tribunal != null) {
				try {
					if (TipoJuizo.PRIMEIRO_GRAU.equals(tipoJuizo)) {
						servico = getRefernciaServico(tribunal.getPjeEndpoint1g());
					} else if (TipoJuizo.SEGUNDO_GRAU.equals(tipoJuizo)) {
						servico = getRefernciaServico(tribunal.getPjeEndpoint2g());
					}
					if (servico != null) {
						servicosMap.put(identificador, servico);
						LOGGER.info("Endpoint inicializado para o tribunal: " + tribunal.getNome());
					} else {
						throw new NegocioException("servicopje.tribunal.naoInicializado");
					}
				} catch (Exception e) {
					LOGGER.error("Nao foi possivel obter referencia ao servico do tribunal: " + tribunal.getNome(), e);
					throw new NegocioException("servicopje.tribunal.naoInicializado");
				}
			} else {
				throw new NegocioException("servicopje.tribunal.naoEncontrado");
			}
		}
		return servico;
	}

	
	/**
	 * @param urlEndpoint
	 * @return
	 * @throws MalformedURLException
	 */
	private Intercomunicacao getRefernciaServico(String urlEndpoint) throws MalformedURLException {
		URL wsdlUrl = new URL(urlEndpoint);
		IntercomunicacaoService service = new IntercomunicacaoService(
				wsdlUrl, SERVICE_QNAME);
		Intercomunicacao servico = service.getPort(Intercomunicacao.class);
		Map<String, Object> context = ((BindingProvider)servico).getRequestContext();
		String endpoint = urlEndpoint;
		if (endpoint.toLowerCase().endsWith("?wsdl")) {
			endpoint = endpoint.substring(0, endpoint.indexOf("?"));
		}
		context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
		return servico;
	}

}
